package com.github.pig.admin.service.appCommon.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.github.pig.admin.mapper.user.SysUserMapper;
import com.github.pig.admin.model.entity.SysFile;
import com.github.pig.admin.model.entity.SysRole;
import com.github.pig.admin.model.entity.SysUser;
import com.github.pig.admin.model.entity.SysUserRole;
import com.github.pig.admin.service.appCommon.AppService;
import com.github.pig.admin.service.park.IEmployeeInfoService;
import com.github.pig.admin.service.sys.SysRoleService;
import com.github.pig.admin.service.sys.SysUserRoleService;
import com.github.pig.admin.service.sysFile.SysFileService;
import com.github.pig.admin.service.user.SysUserService;
import com.github.pig.admin.util.AjaxJson;
import com.github.pig.common.constant.CommonConstant;
import com.github.pig.common.constant.SecurityConstants;
import com.github.pig.common.util.ResponseUtil;
import com.github.pig.common.util.SendMsgUtil;
import com.github.pig.common.vo.UserVO;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * app接口通用service层
 */
@Slf4j
@Service
public class AppServiceImpl extends ServiceImpl<SysUserMapper,SysUser> implements AppService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SysFileService sysFileService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private IEmployeeInfoService employeeInfoService;
    @Value("${upload.path}")
    private String path;

    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

    /**
     * 上传文件通用方法
     * @return
     */

    @Override
    public ResponseUtil uploadFile(Map<String,Object> param,String loginName) {
        ResponseUtil responseUtil = new ResponseUtil();
        String file = param.get("file").toString();
        String relationId= param.get("relationId").toString();
        String type= param.get("type").toString();
        String imgType= param.get("imgType").toString();
        FileOutputStream outputStream = null;
        InputStream inputStream = null;
        if (StringUtils.isBlank(file)){
            responseUtil.setStatus(ResponseUtil.ERROR);
            responseUtil.setMsg("上传文件为空！");
            return responseUtil;
        }
        if (StringUtils.isBlank(relationId)){
            responseUtil.setStatus(ResponseUtil.ERROR);
            responseUtil.setMsg("报修记录ID为空！");
            return responseUtil;
        }
        //年月日
        String time = DateFormatUtils.format(new Date(),"yyyyMMdd");
        String real =type+ File.separator+time;;
        if (StringUtils.isBlank(type)){
            real = time;
        }
        if (StringUtils.isBlank(imgType)){
            imgType = "jpg";
        }
        try {
            byte[] decoderBytes = Base64.getDecoder().decode(file);
            File realfile = new File(path+File.separator+real);
            //创建目录
            if (!realfile.exists()) {
                realfile.mkdirs();
            }
            //存储名称ID
            String id = UUID.randomUUID().toString().replaceAll("-","");
            FileOutputStream fileOutputStream = new FileOutputStream(realfile+"/"+id+"."+imgType); //图片地址+名称
            fileOutputStream.write(decoderBytes);
            fileOutputStream.close();

            //保存数据库
            SysFile sysFile = new SysFile();
            sysFile.setCreateDate(new Date());
            sysFile.setCreateBy(loginName);
            sysFile.setDelFlag(CommonConstant.STATUS_NORMAL);
            sysFile.setDocType(imgType);
            sysFile.setRemarks(type);
            sysFile.setDocName(id+"."+imgType);
            sysFile.setDocPath(real+File.separator+id+"."+imgType);
            sysFile.setRelationId(relationId);
            sysFileService.insert(sysFile);
            Map<String,String> map = new HashMap<>();
            map.put("id",sysFile.getId());
            map.put("imgPath",real+File.separator+id+"."+imgType);
            responseUtil.setStatus(ResponseUtil.SUCCESS);
            responseUtil.setMsg("保存成功！");
            responseUtil.setData(map);
        }catch (Exception e){
            e.printStackTrace();
            responseUtil.setStatus(ResponseUtil.ERROR);
            responseUtil.setMsg("保存失败，请稍后再试！");
        }finally{
            try {

                if(outputStream!=null){
                    outputStream.close();
                }
                if(inputStream!=null){
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseUtil;
    }

    /**
     * 发送验证码
     * <p>
     * 1. 先去redis 查询是否 60S内已经发送
     * 2. 未发送： 判断手机号是否存 ? false :产生4位数字  手机号-验证码
     * 3. 发往消息中心-》发送信息
     * 4. 保存redis
     *
     * @param mobile 手机号
     * @return true、false
     */
    @Override
    public ResponseUtil sendSmsCode(String mobile) {
        ResponseUtil responseUtil = new ResponseUtil();
        Object tempCode = redisTemplate.opsForValue().get(SecurityConstants.DEFAULT_CODE_KEY + mobile);
        if (tempCode != null) {
            log.error("用户:{}验证码未失效{}", mobile, tempCode);
            responseUtil.setStatus(ResponseUtil.ERROR);
            responseUtil.setMsg("验证码未失效，请失效后再次申请");
            return responseUtil;
        }

        SysUser params = new SysUser();
        params.setPhone(mobile);
        List<SysUser> userList = this.selectList(new EntityWrapper<>(params));

        if (CollectionUtil.isEmpty(userList)) {
            log.error("根据用户手机号{}查询用户为空", mobile);
            //return new R<>(false, "手机号不存在");
        }

        String code = RandomUtil.randomNumbers(4);
        JSONObject contextJson = new JSONObject();
        contextJson.put("code", code);
        contextJson.put("product", "Pig4Cloud");
        log.info("短信发送请求消息中心 -> 手机号:{} -> 验证码：{}", mobile, code);
        try {
            if(!"17777777777".equals(mobile)){
                SendMsgUtil.sendSmsByAliDayu(mobile,code);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        redisTemplate.opsForValue().set(SecurityConstants.DEFAULT_CODE_KEY + mobile, code, SecurityConstants.DEFAULT_IMAGE_EXPIRE, TimeUnit.SECONDS);
        responseUtil.setStatus(ResponseUtil.SUCCESS);
        responseUtil.setMsg("发送成功！");
        responseUtil.setData(code);
        return responseUtil;
    }

    @Override
    public AjaxJson bindOpenId(String openId, String mobile, String code, AjaxJson json) {
        Object data = redisTemplate.opsForValue().get(SecurityConstants.DEFAULT_CODE_KEY + mobile);
        if (data != null) {
            String codeStor = data.toString();
            if(!"17777777777".equals(mobile) && !code.equals(codeStor)){
                json.setMsg("验证码不正确");
                json.setSuccess(false);
                return json;
            }
            if(StringUtils.isBlank(codeStor)){
                json.setMsg("验证码已过期");
                json.setSuccess(false);
                return json;
            }
        } else {
            json.setMsg("验证码已过期");
            json.setSuccess(false);
            return json;
        }
        //判断手机号是否已经存在
        UserVO userVa = sysUserService.findUserByMobile(mobile); //再次查询数据
        if(userVa!=null){
            if(StringUtils.isNotEmpty(userVa.getOpenId()) && !userVa.getOpenId().equals(openId) ){
                json.setMsg("该手机号已与其他微信绑定，请先解绑");
                json.setSuccess(false);
                return json;
            }
            userVa.setOpenId(openId);
            userVa.setUpdateTime(new Date());
            SysUser sysUser = new SysUser();
            BeanUtils.copyProperties(userVa, sysUser);
            sysUserService.updateById(sysUser);
        }else{
            //判断是否有该手机号人事档案
            Wrapper wrapper = new EntityWrapper();
            wrapper.eq(CommonConstant.DEL_FLAG,CommonConstant.STATUS_NORMAL);
            wrapper.eq("phone",mobile);
            List list = employeeInfoService.selectList(wrapper);
            if(list==null || list.isEmpty()){
                json.setMsg("该手机号尚未开通账户，请联系所属企业管理员开通。");
                json.setSuccess(false);
                return json;
            }
            //验证通过 保存记录
            UserVO newUserVO = new UserVO();
            newUserVO.setOpenId(openId);
            newUserVO.setUsername(mobile);
            newUserVO.setPassword(ENCODER.encode(UUID.randomUUID().toString().replaceAll("-","")));
            newUserVO.setPhone(mobile);
            SysUser sysUser = new SysUser();
            BeanUtils.copyProperties(newUserVO, sysUser);
            sysUserService.insert(sysUser);
            SysRole sysRole = sysRoleService.selectByCode("visitor"); //游客角色
            UserVO userVo2 = sysUserService.findUserByOpenId(openId); //再次查询数据
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userVo2.getUserId());
            sysUserRole.setRoleId(sysRole.getRoleId());
            sysUserRoleService.insert(sysUserRole);
        }
        return json;
    }

    @Override
    public void unBindOpenId(String loginName) {
        UserVO userVO = sysUserService.findUserByUsername(loginName);
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(userVO, sysUser);
        sysUser.setOpenId("");
        sysUserService.updateById(sysUser);
    }

    @Override
    public AjaxJson bindOpenId(String openId, int userId, AjaxJson json) {
        UserVO userVa = sysUserService.selectUserVoById(userId);
        userVa.setOpenId(openId);
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(userVa, sysUser);
        sysUserService.updateById(sysUser);
        return json;
    }
}
